/*
 * Copyright 2022 Nightingale Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import React, { useState, useEffect, useContext } from 'react';
import _ from 'lodash';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
import { Card, Space, Dropdown, Menu, Tag, Popover, Divider, Tooltip } from 'antd';
import { ShareAltOutlined, SyncOutlined, CloseCircleOutlined, DownOutlined, PlusCircleOutlined, SettingOutlined, LineChartOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { IRawTimeRange } from '@/components/TimeRangePicker';
import { getLabels, getQueryRange, getExprs, setTmpChartData } from '@/services/metricViews';
import { CommonStateContext, basePrefix } from '@/App';
import { getMatchStr } from './utils';
import { IMatch } from '../types';
import Timeseries from '../../../dashboard/Renderer/Renderer/Timeseries';
import Hexbin from '../../../dashboard/Renderer/Renderer/Hexbin';
import { calcsOptions } from '../../../dashboard/Editor/config';
import { colors } from '../../../dashboard/Components/ColorRangeMenu/config';
import LineGraphStandardOptions from '@/components/PromGraphCpt/components/GraphStandardOptions';
import HexbinGraphStandardOptions from './graphStandardOptions/Hexbin';
import { HexbinIcon } from './config';

interface IProps {
  datasourceValue: number;
  metric: string;
  match: IMatch;
  range: IRawTimeRange;
  step?: number;
  onClose: () => void;
}

export default function Graph(props: IProps) {
  const { t, i18n } = useTranslation('objectExplorer');
  const { datasourceList, darkMode } = useContext(CommonStateContext);
  const { datasourceValue, metric, match, range, step, onClose } = props;
  const newGroups = _.map(
    _.filter(match.dimensionLabels, (item) => !_.isEmpty(item.value)),
    'label',
  );
  const [refreshFlag, setRefreshFlag] = useState(_.uniqueId('refreshFlag_'));
  const [calcFunc, setCalcFunc] = useState('');
  const [comparison, setComparison] = useState<string[]>([]);
  const [aggrFunc, setAggrFunc] = useState('avg');
  const [aggrGroups, setAggrGroups] = useState<string[]>(newGroups);
  const [labels, setLabels] = useState<string[]>([]);
  const [series, setSeries] = useState<any[]>([]);
  const [highLevelConfig, setHighLevelConfig] = useState({
    shared: true,
    sharedSortDirection: 'desc',
    legend: true,
    unit: 'sishort', // 2024-05-08 从 'default' 改为 'sishort'
    colorRange: colors[1].value,
    reverseColorOrder: false,
    colorDomainAuto: true,
    colorDomain: [],
    chartheight: 300,
  });
  const [chartType, setChartType] = useState('line');
  const [reduceFunc, setReduceFunc] = useState('last');
  const lineGraphProps = {
    custom: {
      drawStyle: 'lines',
      fillOpacity: 0,
      stack: 'hidden',
      lineInterpolation: 'smooth',
    },
    options: {
      legend: {
        displayMode: highLevelConfig.legend ? 'table' : 'hidden',
      },
      tooltip: {
        mode: highLevelConfig.shared ? 'all' : 'single',
        sort: highLevelConfig.sharedSortDirection,
      },
      standardOptions: {
        util: highLevelConfig.unit,
      },
    },
  };
  const hexbinGraphProps = {
    custom: {
      calc: reduceFunc,
      colorRange: highLevelConfig.colorRange,
      reverseColorOrder: highLevelConfig.reverseColorOrder,
      colorDomainAuto: highLevelConfig.colorDomainAuto,
      colorDomain: highLevelConfig.colorDomain,
    },
    options: {
      standardOptions: {
        util: highLevelConfig.unit,
      },
    },
  };
  const graphStandardOptions = {
    line: <LineGraphStandardOptions highLevelConfig={highLevelConfig} setHighLevelConfig={setHighLevelConfig} data-oid='q3fqp3g' />,
    hexbin: <HexbinGraphStandardOptions highLevelConfig={highLevelConfig} setHighLevelConfig={setHighLevelConfig} data-oid='-ddvepl' />,
  };

  useEffect(() => {
    setAggrGroups(newGroups);
  }, [JSON.stringify(newGroups)]);

  useEffect(() => {
    const matchStr = getMatchStr(match);
    getLabels(datasourceValue, `${metric}${matchStr}`, range).then((res) => {
      setLabels(res);
    });
  }, [refreshFlag, JSON.stringify(match), JSON.stringify(range)]);

  useEffect(() => {
    getQueryRange(datasourceValue, {
      metric,
      match: getMatchStr(match),
      range,
      step,
      aggrFunc,
      aggrGroups,
      calcFunc,
      comparison,
    }).then((res) => {
      setSeries(res);
    });
  }, [refreshFlag, metric, JSON.stringify(match), JSON.stringify(range), step, calcFunc, comparison, aggrFunc, aggrGroups]);

  return (
    <Card
      size='small'
      style={{ marginBottom: 10 }}
      title={
        <Space data-oid='4cohmw-'>
          {metric}
          <Tooltip
            title={
              <div data-oid='u3dasix'>
                {getExprs({
                  metric,
                  match: getMatchStr(match),
                  aggrFunc,
                  aggrGroups,
                  calcFunc,
                  comparison,
                })}
              </div>
            }
            data-oid='9i8d8rm'
          >
            <InfoCircleOutlined data-oid='_.20t9b' />
          </Tooltip>
        </Space>
      }
      className='n9e-metric-views-metrics-graph'
      extra={
        <Space data-oid='6y0i6r8'>
          <Space size={0} style={{ marginRight: 10 }} data-oid='h_vc_f1'>
            <LineChartOutlined
              className={classNames({
                'button-link-icon': true,
                active: chartType === 'line',
              })}
              onClick={() => {
                setChartType('line');
              }}
              data-oid='0gcw0rj'
            />

            <Divider type='vertical' data-oid='5_524_l' />
            <HexbinIcon
              className={classNames({
                'button-link-icon': true,
                active: chartType === 'hexbin',
              })}
              onClick={() => {
                setChartType('hexbin');
              }}
              data-oid='vaxi:w2'
            />
          </Space>
          <Popover placement='left' content={graphStandardOptions[chartType]} trigger='click' autoAdjustOverflow={false} getPopupContainer={() => document.body} data-oid='c-g7oho'>
            <a className='a-icon' data-oid='kw.ad7x'>
              <SettingOutlined data-oid='4a:k8d3' />
            </a>
          </Popover>
          <a className='a-icon' data-oid='tn:lmem'>
            <SyncOutlined
              onClick={() => {
                setRefreshFlag(_.uniqueId('refreshFlag_'));
              }}
              data-oid='9rsk27j'
            />
          </a>
          <a className='a-icon' data-oid='mdi974c'>
            <ShareAltOutlined
              onClick={() => {
                const dataProps = {
                  type: 'timeseries',
                  version: '3.0.0',
                  name: metric,
                  step,
                  range,
                  ...lineGraphProps,
                  targets: _.map(
                    getExprs({
                      metric,
                      match: getMatchStr(match),
                      aggrFunc,
                      aggrGroups,
                      calcFunc,
                      comparison,
                    }),
                    (expr) => {
                      return {
                        expr,
                      };
                    },
                  ),
                  datasourceCate: 'prometheus',
                  datasourceName: _.find(datasourceList, { id: datasourceValue })?.name,
                  datasourceValue,
                };
                setTmpChartData([
                  {
                    configs: JSON.stringify({
                      dataProps,
                    }),
                  },
                ]).then((res) => {
                  const ids = res.dat;
                  window.open(basePrefix + '/chart/' + ids);
                });
              }}
              data-oid='0qdpy4k'
            />
          </a>
          <a className='a-icon' data-oid='_fxb_:f'>
            <CloseCircleOutlined onClick={onClose} data-oid='ee6d0o_' />
          </a>
        </Space>
      }
      data-oid='b-cepak'
    >
      <div data-oid='2-gx8.3'>
        <Space size={'large'} data-oid='a7y-840'>
          <div data-oid='5ysdgik'>
            {t('graph.function')}：
            <Dropdown
              overlay={
                <Menu onClick={(e) => setCalcFunc(e.key === 'clear' ? '' : e.key)} selectedKeys={[calcFunc]} data-oid='x2vax3.'>
                  <Menu.Item key='rate_1m' data-oid='hs8a3a:'>
                    rate_1m
                  </Menu.Item>
                  <Menu.Item key='rate_5m' data-oid='3skkk9a'>
                    rate_5m
                  </Menu.Item>
                  <Menu.Item key='increase_1m' data-oid='vhh0:4l'>
                    increase_1m
                  </Menu.Item>
                  <Menu.Item key='increase_5m' data-oid='bw:.ejn'>
                    increase_5m
                  </Menu.Item>
                  <Menu.Divider data-oid='ys9ygg6'></Menu.Divider>
                  <Menu.Item key='clear' data-oid='wwlo.xu'>
                    clear
                  </Menu.Item>
                </Menu>
              }
              data-oid='tnkvoc0'
            >
              <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()} data-oid='l5xjnei'>
                {calcFunc || t('graph.none')} <DownOutlined data-oid='kz04m2v' />
              </a>
            </Dropdown>
          </div>
          <div data-oid='2.sz4tv'>
            {t('graph.offset')}：
            {comparison.map((ag) => (
              <Tag
                key={ag}
                closable
                onClose={() => {
                  setComparison(_.without(comparison, ag));
                }}
                data-oid='3mt77bz'
              >
                {ag}
              </Tag>
            ))}
            <Dropdown
              overlay={
                <Menu
                  style={{ maxHeight: '200px', overflowY: 'auto' }}
                  onClick={(e) => {
                    if (comparison.indexOf(e.key) === -1) {
                      setComparison([...comparison, e.key]);
                    } else {
                      setComparison(_.without(comparison, e.key));
                    }
                  }}
                  selectedKeys={comparison}
                  data-oid='hksi8:o'
                >
                  <Menu.Item key='1d' data-oid='aophp7h'>
                    1d
                  </Menu.Item>
                  <Menu.Item key='7d' data-oid='ic9k8.d'>
                    7d
                  </Menu.Item>
                </Menu>
              }
              data-oid='uopkzcf'
            >
              <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()} data-oid='hmt:es9'>
                <PlusCircleOutlined data-oid='cl48o3o' />
              </a>
            </Dropdown>
          </div>
          <div data-oid='gvozwn:'>
            {t('graph.aggregation')}：
            <Dropdown
              overlay={
                <Menu onClick={(e) => setAggrFunc(e.key)} selectedKeys={[aggrFunc]} data-oid='xwzk52:'>
                  <Menu.Item key='sum' data-oid='_nuyzmw'>
                    sum
                  </Menu.Item>
                  <Menu.Item key='avg' data-oid='kbzhgow'>
                    avg
                  </Menu.Item>
                  <Menu.Item key='max' data-oid='t5wda.8'>
                    max
                  </Menu.Item>
                  <Menu.Item key='min' data-oid='o-h7cym'>
                    min
                  </Menu.Item>
                </Menu>
              }
              data-oid='lztv0u-'
            >
              <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()} data-oid='gp57nj9'>
                {aggrFunc} <DownOutlined data-oid='mjxtei_' />
              </a>
            </Dropdown>
          </div>
          {aggrFunc ? (
            <div className='graph-config-inner-item' data-oid='crkmd.:'>
              {t('graph.aggregation_by')}：
              {aggrGroups.map((ag) => (
                <Tag
                  key={ag}
                  closable
                  onClose={() => {
                    setAggrGroups(_.without(aggrGroups, ag));
                  }}
                  data-oid='l61l5l-'
                >
                  {ag}
                </Tag>
              ))}
              <Dropdown
                overlay={
                  <Menu
                    style={{ maxHeight: '200px', overflowY: 'auto' }}
                    onClick={(e) => {
                      if (aggrGroups.indexOf(e.key) === -1) {
                        setAggrGroups([...aggrGroups, e.key]);
                      } else {
                        setAggrGroups(_.without(aggrGroups, e.key));
                      }
                    }}
                    selectedKeys={aggrGroups}
                    data-oid='u7cxvoc'
                  >
                    {_.map(
                      _.filter(labels, (n) => n !== '__name__'),
                      (ag) => (
                        <Menu.Item key={ag} data-oid='q9rschg'>
                          {ag}
                        </Menu.Item>
                      ),
                    )}
                  </Menu>
                }
                data-oid='h81y-qo'
              >
                <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()} data-oid='6l.en5_'>
                  <PlusCircleOutlined data-oid='::gytvw' />
                </a>
              </Dropdown>
            </div>
          ) : null}
          {chartType === 'hexbin' && (
            <div data-oid='bzqos67'>
              {t('graph.calc')}：
              <Dropdown
                overlay={
                  <Menu onClick={(e) => setReduceFunc(e.key)} selectedKeys={[reduceFunc]} data-oid='rd3ylt1'>
                    {_.map(calcsOptions, (val, key) => {
                      return (
                        <Menu.Item key={key} data-oid='7e_2hz3'>
                          {t(`dashboard:calcs.${key}`)}
                        </Menu.Item>
                      );
                    })}
                  </Menu>
                }
                data-oid='w6h15wb'
              >
                <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()} data-oid='oo3ugoo'>
                  {t(`dashboard:calcs.${reduceFunc}`)} <DownOutlined data-oid='m2tu6ld' />
                </a>
              </Dropdown>
            </div>
          )}
        </Space>
      </div>
      <div data-oid='453244w'>
        {chartType === 'line' && (
          <Timeseries inDashboard={false} values={lineGraphProps as any} series={series} time={range} themeMode={darkMode ? 'dark' : undefined} data-oid='nw1.llp' />
        )}
        {chartType === 'hexbin' && (
          <div style={{ padding: '20px 0 0 0', height: highLevelConfig.chartheight }} data-oid='gyg7cd-'>
            <Hexbin values={hexbinGraphProps as any} series={series} time={range} data-oid='enhk:w:' />
          </div>
        )}
      </div>
    </Card>
  );
}
